home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / comm1 / s342q12.lha / ctdl.c < prev    next >
C/C++ Source or Header  |  1996-04-03  |  55KB  |  2,269 lines

  1. /*
  2. *       ctdl.c
  3. *
  4. * Command-interpreter code for Citadel.
  5. */
  6. #include "ctdl.h"
  7. char QWKmain(void);
  8.  
  9. /* #define NEED_MSG_PEEKING */
  10. /* #define NEED_MSG_LIST */
  11. /*
  12. *       history
  13. *
  14. * 86Aug16 HAW  Kill history from file because of space problems.
  15. * 84May18 JLS/HAW Greeting modified for coherency.
  16. * 84Apr04 HAW  Upgrade to BDS 1.50a begun.
  17. * 83Mar08 CrT  Aide-special functions installed & tested...
  18. * 83Feb24 CrT/SB Menus rearranged.
  19. * 82Dec06 CrT  2.00 release.
  20. * 82Nov05 CrT  removed main() from room2.c and split into sub-fn()s
  21. */
  22. /*
  23. *       Contents
  24. *
  25. * doAide()    handles Aide-only       commands
  26. * doChat()    handles C(hat)    command
  27. * doEnter()   handles E(nter)   command
  28. * doForget()    handles Z(Forget room)  command
  29. * doGoto()    handles G(oto)    command
  30. * doHelp()    handles H(elp)    command
  31. * doKnown()   handles K(nown rooms)   command
  32. * doLogin()   handles L(ogin)   command
  33. * doLogout()    handles T(erminate)     command
  34. * doMeet()    handles M(eet) User command
  35. * doRead()    handles R(ead)    command
  36. * doRegular()   fanout for above commands
  37. * doSkip()    handles S(kip)    command
  38. * doSysop()   handles sysop-only      commands
  39. * doUngoto()    handles U(ngoto)  command
  40. * getCommand()    prints prompt and gets command char
  41. * greeting()    System-entry blurb etc
  42. * main()      has the central menu code
  43. */
  44. char   ExitToMsdos = FALSE;     /* True when time to bring system down  */
  45. int    exitValue = CRASH_EXIT;
  46. static char NoChatAtAll = FALSE;
  47. char   MeetDisabled;
  48. char   ConsolePassword;
  49. extern CONFIG     cfg;    /* The main variable to be saved      */
  50. extern aRoom      roomBuf;  /* Room buffer    */
  51. extern MessageBuffer    msgBuf; /* Message buffer   */
  52. extern MessageBuffer    tempMess; /* Message buffer   */
  53. extern logBuffer  logBuf; /* Person's log buffer    */
  54. extern logBuffer  logTmp; /* Person's log buffer    */
  55. extern rTable     *roomTab; /* Room index for RAM   */
  56. extern LogTable   *logTab;  /* Log  index for RAM   */
  57. extern struct floor *FloorTab;
  58. extern long       FDSectCount;  /* size of files in directory   */
  59. extern int    thisRoom; /* Current room   */
  60. extern SECTOR_ID  pulledMLoc; /* Loc of msg to be pulled    */
  61. extern MSG_NUMBER pulledMId;  /* Id of msg to be pulled   */
  62. extern char       *who_str;
  63. extern char       remoteSysop;
  64. extern char       onConsole;  /* Where IO is ...    */
  65. extern char       whichIO;  /* Where IO is ...    */
  66. extern char       outFlag;
  67. extern char       loggedIn; /* Are we logged in?    */
  68. extern char       echo;
  69. extern char       newCarrier; /* Just got carrier, hurrah!    */
  70. extern char       justLostCarrier;/* Boo, hiss!   */
  71. extern char       textDownload; /* flag   */
  72. extern char       haveCarrier;
  73. extern char       *baseRoom;
  74. extern char       heldMess;
  75. extern char       anyEcho;
  76. extern char       PrintBanner;
  77. /*
  78. * doAide()
  79. *
  80. * This function handles the aide-only menu.
  81. *
  82. * return FALSE to fall invisibly into default error msg.
  83. */
  84. char doAide(char moreYet, char first)
  85.   {
  86.   label oldName;
  87.   int  rm;
  88.   char chatStack;
  89.   char fname[100];
  90.   char *ValAide[] =
  91.     {
  92.     "Chat           ", "Delete empty rooms  ", "Edit room\n",
  93.     "Insert message ", "Kill room           ", "S\bNot available.\n",
  94.     "\b", " ", ""
  95.  
  96.     };
  97.   extern char *APrivateRoom;
  98.   extern SListBase Moderators;
  99.   if (roomBuf.rbflags.ISDIR == 1 && HalfSysop())
  100.   ExtraOption(ValAide, "Add File\n");
  101.   if (!aide)
  102.     {
  103.     PushBack('E');
  104.  
  105.     }
  106.   if (moreYet)   first = '\0';
  107.   if (first)     PushBack(first);
  108.  
  109.     SpecialMessage("Status:Aide Functions");
  110.  
  111.   RegisterThisMenu("aide.mnu", ValAide);
  112.   switch (GetMenuChar())
  113.     {
  114.     case 'A':
  115.     getString("EFILEN", fname, sizeof fname, 0);
  116.     if (access(fname, 0) != 0)
  117.       {
  118.       Output_Citadel_Message("NOSUCH",(long)fname,NULL,NULL);   /* no such file */
  119.       break;
  120.  
  121.       };
  122.     if (CopyFile(fname, &roomBuf))
  123.       {
  124.       FileCommentUpdate(fname, FALSE);
  125.  
  126.       };
  127.     break;
  128.     case '\b':
  129.     mPrintf("\b \b"); /* not sure why this is necessary */
  130.     return BACKED_OUT;
  131.     case 'C':
  132.     logMessage(TRIED_CHAT, "", 'C');
  133.     if (NoChatAtAll && !SomeSysop())
  134.       {
  135.       if (!MultiBanner("nochat"))
  136.       tutorial("nochat.blb", TRUE);
  137.  
  138.       }
  139.     else
  140.       {
  141.       chatStack = cfg.BoolFlags.noChat;
  142.       cfg.BoolFlags.noChat = FALSE;
  143.       if (whichIO == MODEM) ringSysop();
  144.       else      interact(TRUE) ;
  145.       cfg.BoolFlags.noChat = chatStack;
  146.  
  147.       }
  148.     break;
  149.     case 'D':
  150.     ZeroMsgBuffer(&msgBuf);
  151.     sPrintf(msgBuf.mbtext, "The following empty rooms deleted by %s: ",
  152.     logBuf.lbname);
  153.     if (!getYesNo("CONFRM"))
  154.     break;
  155.     strCpy(oldName, roomBuf.rbname);
  156.     indexRooms();
  157.     if ((rm=roomExists(oldName)) != ERROR)  getRoom(rm);
  158.     else          getRoom(LOBBY);
  159.     aideMessage(NULL, /* noteDeletedMessage== */ FALSE );
  160.     break;
  161.     case 'E':
  162.     renameRoom();
  163.     break;
  164.     case 'I':
  165.     ZeroMsgBuffer(&msgBuf);
  166.     if (
  167.     thisRoom   == AIDEROOM
  168.     ||
  169.     pulledMId  == 0l
  170.     )
  171.       {
  172.       Output_Citadel_Message("NOMSGI",NULL,NULL,NULL); /* no message insertable*/
  173.       break;
  174.  
  175.       }
  176.     if (!getYesNo("CONFRM"))
  177.     break;
  178.     noteAMessage(roomBuf.msg, MSGSPERRM, pulledMId, pulledMLoc);
  179.     putRoom(thisRoom);
  180.     noteRoom();
  181.     sPrintf(msgBuf.mbtext,"Following message inserted in %s> by %s",
  182.     formRoom(thisRoom, FALSE, FALSE), logBuf.lbname);
  183.     aideMessage(NULL, /* noteDeletedMessage == */ TRUE);
  184.     break;
  185.     case 'K':
  186.     if (
  187.     thisRoom == LOBBY
  188.     ||
  189.     thisRoom == MAILROOM
  190.     ||
  191.     thisRoom == AIDEROOM
  192.     )
  193.       {
  194.       Output_Citadel_Message("NOKILL",NULL,NULL,NULL);
  195.       break;
  196.  
  197.       }
  198.     if (!getYesNo("CONFRM"))   break;
  199.     ZeroMsgBuffer(&msgBuf);
  200.     sPrintf( msgBuf.mbtext, "%s> killed by %s",roomBuf.rbname,logBuf.lbname);
  201.     aideMessage(NULL, /* noteDeletedMessage == */ FALSE);
  202.     KillInfo(roomBuf.rbname);
  203.     roomBuf.rbflags.INUSE = FALSE;
  204.     putRoom(thisRoom);
  205.     noteRoom();
  206.     getRoom(LOBBY);
  207.     break;
  208.     case 'S':
  209.     #ifdef NEED_AVAILABLE
  210.     changeDate();
  211.     #endif
  212.     break;
  213.  
  214.     }
  215.   return GOOD_SELECT;
  216.  
  217.   }
  218. /*
  219. * doChat()
  220. *
  221. * Chatting!
  222. */
  223. char doChat(char moreYet, char first)
  224.   {
  225.   if (moreYet)   first = '\0';
  226.   if (first)     oChar(first);
  227.   if (whichIO != MODEM)
  228.     {
  229.     interact(TRUE) ;
  230.     if (whichIO == CONSOLE)
  231.     if (getYesNo("MODEMM"))
  232.       {
  233.       whichIO = MODEM;
  234.       setUp(FALSE);
  235.       if (!gotCarrier()) EnableModem(FALSE);
  236.  
  237.       }
  238.  
  239.     }
  240.   else
  241.     {
  242.     logMessage(TRIED_CHAT, "", 'C');
  243.     if (cfg.BoolFlags.noChat)
  244.       {
  245.       if (!MultiBanner("nochat"))
  246.       tutorial("nochat.blb", TRUE);
  247.       return GOOD_SELECT;
  248.  
  249.       }
  250.     ringSysop();
  251.  
  252.     }
  253.   return GOOD_SELECT;
  254.  
  255.   }
  256. /*
  257. * doEnter()
  258. *
  259. * This function handles the E(nter) command.
  260. */
  261. char doEnter(char moreYet, char first)
  262.   {
  263.   #define CONFIGURATION   0
  264.   #define MESSAGE   1
  265.   #define PASSWORD  2
  266.   #define ROOM    3
  267.   #define ENTERFILE       4
  268.   #define CONTINUED       5
  269.   #define NETWORK   6
  270.   #define DEFAULT_MESSAGE 7
  271.   char what;      /* one of above seven */
  272.   SListBase  ESelects =
  273.     {
  274.     NULL, FindSelect, NULL, NoFree, NULL
  275.  
  276.     };
  277.   char *EnterOpts[] =
  278.     {
  279.     TERM "\r", TERM "\n", NTERM "Xmodem", NTERM "Ymodem",
  280.     #ifdef WXMODEM_AVAILABLE
  281.     NTERM "Wxmodem",
  282.     #endif
  283.     TERM "Configuration", TERM "Message", TERM "Password",
  284.     TERM "Room", TERM "Held Message", TERM "Net-Message",
  285.     /* These are for external protocols -- don't delete them! */
  286.     " ", " ", " ",
  287.     " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", ""
  288.  
  289.     };
  290.   char abort, Protocol, again;
  291.   char *letter, cmdbuf[30];
  292.   if (loggedIn && roomBuf.rbflags.ISDIR == 1)
  293.   ExtraOption(EnterOpts, TERM "F");
  294.   AddExternProtocolOptions(EnterOpts, TRUE);
  295.   if (moreYet)   first = '\0';
  296.   abort       = FALSE  ;
  297.   if (thisRoom != MAILROOM && !loggedIn &&
  298.   !cfg.BoolFlags.unlogEnterOk)
  299.     {
  300.     Output_Citadel_Message("ENTERM",NULL,NULL,NULL);
  301.     return GOOD_SELECT;
  302.  
  303.     }
  304.   SpecialMessage("Status:Enter");
  305.   if (first)     PushBack(first);
  306.   do
  307.     {
  308.     again = FALSE;
  309.     outFlag = OUTOK;
  310.     Protocol  = ASCII  ;
  311.     what  = DEFAULT_MESSAGE;
  312.     if (CmdMenuList(EnterOpts, &ESelects, "entopt.mnu", cmdbuf,
  313.     moreYet, TRUE) == BACKED_OUT)
  314.     return BACKED_OUT;
  315.     letter = cmdbuf;
  316.     do
  317.       {
  318.       switch (*letter)
  319.         {
  320.         case '\r':
  321.         case '\n':
  322.         break;
  323.         #ifdef WXMODEM_AVAILABLE
  324.         case 'X':
  325.         case 'Y':
  326.         case 'W':
  327.         Protocol = (*letter == 'Y') ? YMDM : (*letter == 'X') ? XMDM : WXMDM;
  328.         break;
  329.         #else
  330.         case 'X':
  331.         case 'Y':
  332.         Protocol = (*letter == 'Y') ? YMDM : XMDM;
  333.         break;
  334.         #endif
  335.         case 'F':
  336.         if (Protocol == ASCII)
  337.           {
  338.           mPrintf("\b\bXmodem F ");
  339.           Protocol = XMDM;
  340.  
  341.           }
  342.         mPrintf("\bile Upload ");
  343.         if (!roomBuf.rbflags.UPLOAD || logBuf.lbflags.TWIT)
  344.           {
  345.           Output_Citadel_Message("NOUPLD",NULL,NULL,NULL);
  346.           abort = TRUE;
  347.  
  348.           }
  349.         what    = ENTERFILE;
  350.         break;
  351.         case 'C':
  352.         again = reconfigure();
  353.         what  = CONFIGURATION;
  354.         break;
  355.         case 'M':
  356.         what  = MESSAGE;
  357.         break;
  358.         case 'P':
  359.         what  = PASSWORD     ;
  360.         break;
  361.         case 'R':
  362.         if (!cfg.BoolFlags.nonAideRoomOk && !aide)
  363.           {
  364.           Output_Citadel_Message("NOTAID",NULL,NULL,NULL);
  365.           abort   = TRUE;
  366.           break;
  367.  
  368.           }
  369.         if (!loggedIn)
  370.           {
  371.           Output_Citadel_Message("LGICRR",NULL,NULL,NULL);
  372.           abort = TRUE;
  373.           break;
  374.  
  375.           }
  376.         if (logBuf.lbflags.TWIT)
  377.           {
  378.           Output_Citadel_Message("TWITNR",NULL,NULL,NULL);
  379.           abort = TRUE;
  380.           break;
  381.  
  382.           }
  383.         what  = ROOM;
  384.         break;
  385.         case 'H':
  386.         what = CONTINUED;
  387.         Protocol   = ASCII; /* can't do this using protocol */
  388.         break;
  389.         case 'N':
  390.         if( logBuf.lbflags.NET_PRIVS )
  391.           what = NETWORK;
  392.         else Output_Citadel_Message("NONETP",NULL, NULL, NULL);
  393.         break;
  394.         default:
  395.         if ((Protocol = FindProtocolCode(*letter, TRUE)) == -1)
  396.         abort = TRUE;
  397.  
  398.         }
  399.       ++letter;
  400.  
  401.       }
  402.     while (moreYet && !abort && *letter);
  403.  
  404.     }
  405.   while (again);
  406.   KillList(&ESelects);
  407.   doCR();
  408.   if (!abort)
  409.     {
  410.     if (whichIO != CONSOLE && loggedIn &&
  411.     (thisRoom == MAILROOM || roomTab[thisRoom].rtflags.ANON))
  412.     echo = CALLER;
  413.     switch (what)
  414.       {
  415.       case DEFAULT_MESSAGE:
  416.       if (Protocol != ASCII)
  417.         {
  418.         Output_Citadel_Message("MSGTRN",NULL,NULL,NULL);
  419.         }
  420.       case   MESSAGE:   makeMessage(Protocol);  break;
  421.       case  PASSWORD:   newPW()   ; break;
  422.       case      ROOM:   makeRoom()    ; break;
  423.       case ENTERFILE:   upLoad(Protocol,NULL,TRUE)  ; break;
  424.       case CONTINUED:   hldMessage(FALSE) ; break;
  425.       case   NETWORK:   netMessage(Protocol); break;
  426.  
  427.       }
  428.     echo = BOTH;
  429.  
  430.     }
  431.   return GOOD_SELECT ;
  432.  
  433.   }
  434. /*
  435. * doForget()
  436. *
  437. * This function handles the (Forget room) command.
  438. */
  439. char doForget(char expand)
  440.   {
  441.   if (!expand)
  442.     {
  443.     mPrintf("%s\n ", roomBuf.rbname);
  444.     if (thisRoom == LOBBY    ||
  445.     thisRoom == MAILROOM ||
  446.     thisRoom == AIDEROOM)
  447.       {
  448.       Output_Citadel_Message("CANTFG",NULL,NULL,NULL);
  449.       return GOOD_SELECT ;
  450.  
  451.       }
  452.     if (!getYesNo("CONFRM"))   return GOOD_SELECT;
  453.     SetKnown(FORGET_OFFSET, 0, thisRoom, &logBuf);
  454.     gotoRoom(baseRoom, 'S');
  455.  
  456.     }
  457.   else
  458.     {
  459.     /* mPrintf("\b\b "); */
  460.     listRooms(FORGOTTEN);
  461.  
  462.     }
  463.   return GOOD_SELECT;
  464.  
  465.   }
  466. /*
  467. * doGoto()
  468. *
  469. * This function handles the G(oto) command.
  470. */
  471. char doGoto(char expand)
  472.   {
  473.   label roomName;
  474.   int   oldRoom;
  475.   outFlag = IMPERVIOUS;
  476.   if (!expand)
  477.     {
  478.     oldRoom = thisRoom;
  479.     gotoRoom("", 'R');
  480.     if (oldRoom == thisRoom && loggedIn && !expert)
  481.     Output_Citadel_Message("NOMMSG",NULL,NULL,NULL);
  482.     return GOOD_SELECT;
  483.  
  484.     }
  485.   if (getNormStr("", roomName, NAMESIZE, BS_VALID) == BACKED_OUT)
  486.     {
  487.     return BACKED_OUT;
  488.  
  489.     }
  490.   if (roomName[0] == '?')
  491.     {
  492.     listRooms(NOT_INTRO);
  493.  
  494.     }
  495.   else
  496.   gotoRoom(roomName, 'R');
  497.   return GOOD_SELECT;
  498.  
  499.   }
  500. /*
  501. * doHelp()
  502. *
  503. * This function the handles the H(elp) command.
  504. */
  505. char doHelp(char expand)
  506.   {
  507.   label fileName;
  508.  
  509.   SpecialMessage("Status:Help");
  510.  
  511.   if (!expand)
  512.     {
  513.     mPrintf("\n\n");
  514.     printHelp("mainhelp.hlp");
  515.     return GOOD_SELECT;
  516.  
  517.     }
  518.   if (getNormStr("", fileName, (sizeof fileName) - 4, BS_VALID) == BACKED_OUT)
  519.   return BACKED_OUT;
  520.   if (strLen(fileName) == 0)
  521.   strCpy(fileName, "mainhelp");
  522.   if (fileName[0] == '?')     printHelp("helpopt.hlp");
  523.   else
  524.     {
  525.     /* adding the extention makes things look simpler for   */
  526.     /* the user... and restricts the files which can be read  */
  527.     strCat(fileName, ".hlp");
  528.     printHelp(fileName);
  529.  
  530.     }
  531.   return GOOD_SELECT;
  532.  
  533.   }
  534. /*
  535. * doKnown()
  536. *
  537. * This function handles the K(nown rooms) command.
  538. */
  539. char doKnown(char expand)
  540.   {
  541.   char select = ERROR, c[2], again;
  542.   label matchstr;
  543.   char *KMenuOpts[] =
  544.     {
  545.     TERM "Anonymous rooms\n", TERM "Match", TERM "Directory rooms\n",
  546.     TERM "Shared rooms\n", TERM "Private rooms\n",
  547.     TERM "Z\bForgotten rooms\n", TERM "Information", TERM "Read-only\n",
  548.     TERM "\r", TERM "\n", ""
  549.  
  550.     };
  551.   SListBase  KSelects =
  552.     {
  553.     NULL, FindSelect, NULL, NoFree, NULL
  554.  
  555.     };
  556.  
  557.   SpecialMessage("Status:Known");
  558.  
  559.   if (!expand)
  560.     {
  561.     mPrintf("\n ");
  562.     listRooms(NOT_INTRO);
  563.  
  564.     }
  565.   else
  566.     {
  567.     do
  568.       {
  569.       again = FALSE;
  570.       if (CmdMenuList(KMenuOpts, &KSelects, "known.mnu", c, TRUE, TRUE)
  571.       == BACKED_OUT)
  572.       return BACKED_OUT;
  573.       switch (c[0])
  574.         {
  575.         case 'I':
  576.         AllInfo();
  577.         break;
  578.         case 'A':
  579.         select = ANON_SEL;
  580.         break;
  581.         case 'M':
  582.         if (getNormStr("",matchstr,NAMESIZE, BS_VALID) == BACKED_OUT)
  583.           {
  584.           again = TRUE;
  585.           select = ERROR;
  586.           PushBack('\b');
  587.           oChar(' ');
  588.  
  589.           }
  590.         else select = MATCH_SEL;
  591.         break;
  592.         case 'D':
  593.         select = DR_SEL;
  594.         break;
  595.         case 'S':
  596.         select = SH_SEL;
  597.         break;
  598.         case 'P':
  599.         select = PR_SEL;
  600.         break;
  601.         case 'Z':
  602.         select = FORGOTTEN;
  603.         break;
  604.         case 'R':
  605.         select = READONLY;
  606.         break;
  607.         case '\r':
  608.         doCR();
  609.         case '\n':
  610.         strCpy(matchstr, "");
  611.         select = MATCH_SEL;
  612.         break;
  613.  
  614.         }
  615.       if (select != MATCH_SEL && select != ERROR)
  616.       listRooms(select);
  617.       else if (select != ERROR)
  618.       searchRooms(matchstr);
  619.  
  620.       }
  621.     while (again);
  622.  
  623.     }
  624.   KillList(&KSelects);
  625.   return GOOD_SELECT;
  626.  
  627.   }
  628. /*
  629. * doLogin()
  630. *
  631. * This function handles the L(ogin) command.
  632. */
  633. char doLogin(char moreYet)
  634.   {
  635.   label passWord;
  636.   if (!moreYet)   mPrintf("\n");
  637.  
  638.   SpecialMessage("Status:Login");
  639.  
  640.   if (loggedIn)
  641.     {
  642.     Output_Citadel_Message("ALRULG",NULL,NULL,NULL);
  643.     return GOOD_SELECT;
  644.  
  645.     }
  646.   echo  = CALLER;
  647.   if (getNormStr(moreYet ? "" : "ULGPWD",
  648.   passWord, NAMESIZE, (moreYet) ? BS_VALID : NO_ECHO) ==
  649.   BACKED_OUT)
  650.     {
  651.     return BACKED_OUT;
  652.  
  653.     }
  654.   echo  = BOTH;
  655.   login(passWord);
  656.   return GOOD_SELECT;
  657.  
  658.   }
  659. /*
  660. * doLogout()
  661. *
  662. * This function handles the T(erminate) command.
  663. */
  664. char doLogout(char expand, char first)
  665.   {
  666.   char cx;
  667.  
  668.   SpecialMessage("Status:Terminating");
  669.  
  670.   if (expand)   first = '\0';
  671.   outFlag = IMPERVIOUS;
  672.   if (heldMess && !cfg.BoolFlags.HoldOnLost)
  673.     {
  674.     Output_Citadel_Message("HOLDMS",NULL,NULL,NULL);
  675.     mAbort(); /* clear any first-run input fromuser */
  676.  
  677.     }
  678.   if (first)   oChar(first);
  679.   if( first )
  680.     {
  681.     cx = first;
  682.  
  683.     }
  684.   else cx = iChar();
  685.   switch (toUpper( cx ))
  686.     {
  687.     case '\b':
  688.     if (expand) return BACKED_OUT;
  689.     default:
  690.     Output_Citadel_Message("LGOPTS",NULL,NULL,NULL);
  691.     break;
  692.     case 'Q':
  693.     mPrintf("uit-also\n ");
  694.     if (!expand)
  695.       {
  696.       if (!getYesNo("CONFRM"))   break;
  697.  
  698.       }
  699.     if (!onLine()) break;
  700.     terminate( /* hangUp == */ TRUE, TRUE);
  701.     break;
  702.     case 'S':
  703.     mPrintf("tay\n ");
  704.     terminate( /* hangUp == */ FALSE, TRUE);
  705.     break;
  706.     case 'A':
  707.     mPrintf("bort\n ");
  708.     terminate( /* hangUp == */ TRUE, FALSE);
  709.  
  710.     }
  711.   outFlag = OUTOK;
  712.   return GOOD_SELECT;
  713.  
  714.   }
  715. OptValues Opt;
  716. char revOrder;  /* Udderly HIDEOUS kludge.  MOOOOOO! */
  717. char PhraseUser;
  718. /*
  719. * doMeet()
  720. *
  721. * This function handles the M(eet) User command.
  722. */
  723. char doMeet(char moreYet)
  724.   {
  725.   label User;
  726.   int   logNo;
  727.  
  728.     SpecialMessage("Status:Meet Users");
  729.  
  730.   if (!moreYet) doCR();
  731.   if (getNormStr(moreYet ? "" : "USMEET",
  732.   User, NAMESIZE, QUEST_SPECIAL | BS_VALID) == BACKED_OUT)
  733.     {
  734.     return BACKED_OUT;
  735.  
  736.     }
  737.   if (strLen(User) != 0)
  738.     {
  739.     if (User[0] == '?')
  740.       {
  741.       BioDirectory();
  742.       return GOOD_SELECT;
  743.  
  744.       }
  745.     logNo = findPerson(User, &logTmp);
  746.     if (logNo == ERROR)
  747.       {
  748.       Output_Citadel_Message("NOPERS",(long)User,NULL,NULL);
  749.       }
  750.     else
  751.       {
  752.       if (GetBioInfo(logNo))
  753.         {
  754.         Output_Citadel_Message("BIOOFU",(long)logTmp.lbname,NULL,NULL);
  755.         doCR();
  756.         mPrintf("%s\n ", msgBuf.mbtext);
  757.  
  758.         }
  759.       else  Output_Citadel_Message("NOBIOU",(long)logTmp.lbname,NULL,NULL);
  760.       }
  761.  
  762.     }
  763.   return GOOD_SELECT;
  764.  
  765.   }
  766. /*
  767. * doRead()
  768. *
  769. * This function handles the R(ead) command.
  770. */
  771. static void *FindUser(char *element, int x);
  772. int   UserOptAdd(char *str);
  773. char doRead(char moreYet, char first)
  774.   {
  775.   char abort = FALSE,
  776.   Compressed = FALSE,
  777.   extDir,
  778.   doDir,
  779.   again,
  780.   hostFile,
  781.   whichMess,
  782.   status = FALSE,
  783.   SrchUser,
  784.   srchPhrase,
  785.   protocol,
  786.   global,
  787.   filestuff = FALSE,
  788.   ReadArchive;
  789.   char *letter, secondletter;
  790.   char fileName[100];
  791.   int    CurRoom;
  792.   extern FILE* upfd;
  793.   SListBase  RSelects =
  794.     {
  795.     NULL, FindSelect, NULL, NoFree, NULL
  796.  
  797.     };
  798.   SListBase  CSelects =
  799.     {
  800.     NULL, FindSelect, NULL, NoFree, NULL
  801.  
  802.     };
  803.   extern char journalMessage, FormatFlag;
  804.   extern int outPut;
  805.   char *ReadOpts[] =
  806.     {
  807.     TERM "\r", TERM "\n",
  808.     #ifdef NO_DeARC_SUPPORT
  809.     TERM "Archive-Directory(s)\n",
  810.     #else
  811.     TERM "Archive",
  812.     #endif
  813.     TERM "Forward", NTERM "Global", NTERM "Local-only", TERM "New",
  814.     TERM "Old-reverse", TERM "Reverse", TERM "Status\n", NTERM "Xmodem",
  815.     #ifdef WXMODEM_AVAILABLE
  816.     NTERM "Wxmodem",
  817.     #endif
  818.     NTERM "Ymodem", NTERM "User", NTERM "Phrase",
  819.     /* these two are here rather than optional due to .RGE/.RGD */
  820.     TERM "Directory", TERM "Extended-Directory", " ", " ", " ", " ",
  821.     " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
  822.     " ", " ", " ", " ", " ", ""
  823.  
  824.     };
  825.   #ifndef NO_DeARC_SUPPORT
  826.   char *CompOpts[] =
  827.     {
  828.     TERM "Directory(s)\n", TERM "File(s)\n", TERM "T\bFile(s)\n",
  829.     TERM "B\bFile(s)\n", TERM "\nDirectory(s)", ""
  830.  
  831.     };
  832.   #endif
  833.   char  cmdbuf[40];
  834.   whichMess = NEWoNLY;
  835.   if (moreYet)   first = '\0';
  836.   zero_struct(Opt);
  837.   Opt.Date = -1l;
  838.   InitListValues(&Opt.Users, FindUser, NULL, free, NULL);
  839.   if (thisRoom == MAILROOM && !loggedIn  &&
  840.   !cfg.BoolFlags.unlogReadOk)
  841.     {
  842.     showMessages(whichMess, revOrder,
  843.     logBuf.lbvisit[logBuf.lbgen[thisRoom] & CALLMASK],
  844.     OptionValidate);
  845.     return GOOD_SELECT;
  846.  
  847.     }
  848.   if (!loggedIn  &&  !cfg.BoolFlags.unlogReadOk)
  849.     {
  850.     Output_Citadel_Message("READMM",NULL,NULL,NULL);
  851.     return GOOD_SELECT;
  852.  
  853.     }
  854.   if (first)     PushBack(first);
  855.   if (roomBuf.rbflags.ISDIR == 1 && loggedIn && !logBuf.lbflags.TWIT)
  856.     {
  857.     ExtraOption(ReadOpts, TERM "Binary file(s)");
  858.     ExtraOption(ReadOpts, TERM "Textfile(s)");
  859.  
  860.     }
  861.   if (AnyCompression())
  862.   ExtraOption(ReadOpts, NTERM "Compressed");
  863.   AddExternProtocolOptions(ReadOpts, FALSE);
  864.   if (HalfSysop())
  865.   ExtraOption(ReadOpts, TERM "Invited-users");
  866.  
  867.   SpecialMessage("Status:Reading");
  868.  
  869.   do
  870.     {
  871.     again = FALSE;
  872.     protocol = ASCII;
  873.     whichMess = NEWoNLY;
  874.     extDir = doDir = hostFile = SrchUser = srchPhrase =
  875.     global = ReadArchive = PhraseUser = revOrder = FALSE;
  876.     if (CmdMenuList(ReadOpts, &RSelects, "readopt.mnu", cmdbuf, moreYet, TRUE) ==
  877.     BACKED_OUT)
  878.     return BACKED_OUT;
  879.     letter = cmdbuf;
  880.     do
  881.       {
  882.       outFlag = OUTOK;
  883.       switch (*letter)
  884.         {
  885.         case '\r':
  886.         doCR();
  887.         case '\n':
  888.         break;
  889.         case 'C':
  890.         Compressed = TRUE;
  891.         break;
  892.         case 'A':
  893.         if (   ( global || roomBuf.rbflags.ISDIR )
  894.             && ( logBuf.lbflags.DL_PRIVS || aide ) )
  895.           {
  896.           if (roomBuf.rbflags.DOWNLOAD || HalfSysop())
  897.             {
  898.             if (CmdMenuList(CompOpts, &CSelects, "", cmdbuf, TRUE,
  899.             FALSE) == BACKED_OUT)
  900.               {
  901.               again = TRUE;
  902.               PushBack('\b');
  903.  
  904.               }
  905.             else
  906.               {
  907.               switch (cmdbuf[0])
  908.                 {
  909.                 case '\n':
  910.                 case '\r':
  911.                 case 'D':
  912.                 ReadArchive = 1;
  913.                 break;
  914.                 case 'T':
  915.                 case 'B':
  916.                 case 'F':
  917.                 ReadArchive = 2;
  918.                 break;
  919.                 default:
  920.                 abort = TRUE;
  921.  
  922.                 }
  923.               break;
  924.  
  925.               }
  926.  
  927.             }
  928.           else
  929.             {
  930.             Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  931.             abort = TRUE;
  932.             break;
  933.  
  934.             }
  935.  
  936.           }
  937.         else
  938.           {
  939.           Output_Citadel_Message("NOTDIR",NULL,NULL,NULL);
  940.           abort = TRUE;
  941.           break;
  942.           };
  943.  
  944.         break;
  945.         case 'F':
  946.         revOrder    = FALSE;
  947.         whichMess   = OLDaNDnEW;
  948.         goto commondate;
  949.         case 'G':
  950.         global  = TRUE;
  951.         break;
  952.         case 'L':
  953.         Opt.LocalOnly = TRUE;
  954.         break;
  955.         case 'N':
  956.         whichMess   = NEWoNLY;
  957.         goto commondate;
  958.         case 'O':
  959.         revOrder    = TRUE;
  960.         whichMess   = OLDoNLY;
  961.         goto commondate;
  962.         case 'R':
  963.         revOrder    = TRUE;
  964.         whichMess   = OLDaNDnEW;
  965.         commondate:
  966.         if (moreYet)
  967.           {
  968.           if (getString("", fileName, NAMESIZE,
  969.           BS_VALID | QUEST_SPECIAL) == BACKED_OUT)
  970.             {
  971.             again = TRUE;
  972.             oChar(' ');
  973.             PushBack('\b');
  974.             break;
  975.  
  976.             }
  977.           if (fileName[0] == '?')
  978.             {
  979.             tutorial("readdate.blb", TRUE);
  980.             KillList(&RSelects);
  981.             return GOOD_SELECT;
  982.  
  983.             }
  984.           if (strLen(fileName) != 0)
  985.           if (ReadDate(fileName, &Opt.Date) == ERROR)
  986.             {
  987.             Output_Citadel_Message("INVLDD",NULL,NULL,NULL);
  988.             KillList(&RSelects);
  989.             return GOOD_SELECT;
  990.  
  991.             }
  992.  
  993.           }
  994.         else
  995.           {
  996.           doCR();
  997.  
  998.           }
  999.         break;
  1000.         case 'S':
  1001.         status      = TRUE;
  1002.         break;
  1003.         #ifdef WXMODEM_AVAILABLE
  1004.         case 'X':
  1005.         case 'W':
  1006.         case 'Y':
  1007.         protocol    = (*letter == 'W') ? WXMDM :
  1008.         (*letter == 'X') ? XMDM : YMDM;
  1009.         break;
  1010.         #else
  1011.         case 'X':
  1012.         case 'Y':
  1013.         protocol    = (*letter == 'X') ? XMDM : YMDM;
  1014.         break;
  1015.         #endif
  1016.         case 'B':
  1017.         case 'T':
  1018.         filestuff = TRUE;
  1019.         case 'E':
  1020.         case 'D':
  1021.         if (!logBuf.lbflags.DL_PRIVS && !aide)
  1022.           {
  1023.           Output_Citadel_Message("NODLDP",NULL,NULL,NULL);
  1024.           abort = TRUE;
  1025.           break;
  1026.  
  1027.           }
  1028.         if (filestuff)
  1029.           {
  1030.           if (roomBuf.rbflags.DOWNLOAD == 1 || TheSysop() ||
  1031.           remoteSysop)
  1032.             {
  1033.             hostFile      = TRUE ;
  1034.             textDownload    = (*letter == 'T') ? TRUE : FALSE;
  1035.             if (textDownload && protocol == ASCII)
  1036.               {
  1037.               char cx;
  1038.               cx = modIn();
  1039.               switch (secondletter = toUpper(cx))
  1040.                 {
  1041.                 case '\b':
  1042.                 again = TRUE;
  1043.                 PushBack('\b');
  1044.                 break;
  1045.                 case 'F':
  1046.                 mPrintf("Formatted");
  1047.                 FormatFlag = TRUE;
  1048.                 break;
  1049.                 default:
  1050.                 PushBack(secondletter);
  1051.                 case '\r':
  1052.                 case '\n':
  1053.                 case ' ':
  1054.                 doCR();
  1055.  
  1056.                 }
  1057.  
  1058.               }
  1059.  
  1060.             }
  1061.           else
  1062.             {
  1063.             Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  1064.             abort = TRUE;
  1065.  
  1066.             }
  1067.  
  1068.           }
  1069.         else
  1070.           {
  1071.           if (roomBuf.rbflags.ISDIR == 1 || global)
  1072.             {
  1073.             if (global || roomBuf.rbflags.DOWNLOAD || TheSysop()
  1074.             || remoteSysop)
  1075.               {
  1076.               if (getNormStr("", fileName, sizeof fileName,
  1077.               BS_VALID) == BACKED_OUT)
  1078.                 {
  1079.                 PushBack('\b');
  1080.                 again = TRUE;
  1081.                 oChar(' ');
  1082.                 break;
  1083.  
  1084.                 }
  1085.               if (*letter == 'D') doDir   = TRUE;
  1086.               else      extDir  = TRUE;
  1087.               break;
  1088.  
  1089.               }
  1090.             else
  1091.               {
  1092.               Output_Citadel_Message("NODLDS",NULL,NULL,NULL);
  1093.               abort = TRUE;
  1094.               break;
  1095.  
  1096.               }
  1097.  
  1098.             }
  1099.           else
  1100.             {
  1101.             Output_Citadel_Message("NOTDIR",NULL,NULL,NULL);
  1102.             abort = TRUE;
  1103.  
  1104.             }
  1105.  
  1106.           }
  1107.         break;
  1108.         case 'I':
  1109.         if (doInviteDisplay() == BACKED_OUT)
  1110.           {
  1111.           PushBack('\b');
  1112.           again = TRUE;
  1113.           oChar(' ');
  1114.           break;
  1115.  
  1116.           }
  1117.         KillList(&RSelects);
  1118.         return  GOOD_SELECT;
  1119.         case 'P':
  1120.         srchPhrase = TRUE;
  1121.         PhraseUser = TRUE;
  1122.         break;
  1123.         case 'U':
  1124.         SrchUser = TRUE;
  1125.         PhraseUser = TRUE;
  1126.         break;
  1127.         default:
  1128.         if ((protocol = FindProtocolCode(*letter, FALSE)) == -1)
  1129.         abort = TRUE;
  1130.  
  1131.         }
  1132.       letter++;
  1133.  
  1134.       }
  1135.     while (moreYet && !abort && *letter);
  1136.  
  1137.     }
  1138.   while (again);
  1139.   KillList(&RSelects);
  1140.   KillList(&CSelects);
  1141.   if (abort) return GOOD_SELECT;
  1142.   if (status)
  1143.     {
  1144.     systat();
  1145.     return GOOD_SELECT;
  1146.  
  1147.     }
  1148.   if (ReadArchive)
  1149.     {
  1150.     #ifdef NO_DeARC_SUPPORT
  1151.     getNormStr("ARCHFN", fileName, sizeof fileName, 0);
  1152.     if (srchPhrase)
  1153.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1154.     mPrintf("\n %7s%8s%5s Name...\n ", "Crunched", "Normal", "date");
  1155.     wildCard(CompressedDir, fileName, TRUE, Opt.Phrase, TRUE);
  1156.     #else
  1157.     if (ReadArchive == 1)
  1158.       {
  1159.       getNormStr("ARCHFN", fileName, sizeof fileName, 0);
  1160.       if (srchPhrase)
  1161.       getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1162.       if (strchr(fileName, '.') == NULL) strCat(fileName, ".arc");
  1163.       wildCard(CompressedDir, fileName, TRUE, Opt.Phrase, TRUE);
  1164.  
  1165.       }
  1166.     else if (ReadArchive == 2)
  1167.     SendArcFiles(protocol);
  1168.     #endif
  1169.     return GOOD_SELECT;
  1170.  
  1171.     }
  1172.   if (doDir || extDir)
  1173.     {
  1174.     if (srchPhrase)
  1175.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1176.     if (!global)
  1177.     doDirectory(doDir, fileName, Opt.Phrase);
  1178.     else
  1179.       {
  1180.       CurRoom = thisRoom;
  1181.       /* should we have tableRunner() do this for us? */
  1182.       for (thisRoom = 0; outFlag == OUTOK && thisRoom < MAXROOMS;
  1183.       thisRoom++)
  1184.       if (roomTab[thisRoom].rtflags.INUSE &&
  1185.       roomTab[thisRoom].rtflags.ISDIR &&
  1186.       (roomTab[thisRoom].rtflags.DOWNLOAD || SomeSysop()) &&
  1187.       knowRoom(&logBuf, thisRoom) == KNOW_ROOM)
  1188.         {
  1189.         getRoom(thisRoom);
  1190.         mPrintf("\n (%s)\n ", roomBuf.rbname);
  1191.         doCR();   /* nice left side now */
  1192.         doDirectory(doDir, fileName, Opt.Phrase);
  1193.         if (outFlag == OUTNEXT) outFlag = OUTOK;
  1194.  
  1195.         }
  1196.       getRoom(CurRoom);
  1197.  
  1198.       }
  1199.     if (journalMessage)
  1200.       {
  1201.       if (redirect(NULL))
  1202.         {
  1203.         doDirectory(doDir, fileName, Opt.Phrase);
  1204.         undirect();
  1205.         /* fclose(upfd);
  1206.         outPut = NORMAL; */
  1207.  
  1208.         }
  1209.       journalMessage = FALSE;
  1210.  
  1211.       }
  1212.     return GOOD_SELECT;
  1213.  
  1214.     }
  1215.   if (hostFile)
  1216.     {
  1217.     if (srchPhrase)
  1218.     getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1219.     TranFiles(protocol, Opt.Phrase);
  1220.     FormatFlag = FALSE;
  1221.     return GOOD_SELECT;
  1222.  
  1223.     }
  1224.   if (SrchUser)
  1225.     {
  1226.     getList(UserOptAdd, "Users", NAMESIZE * 3, FALSE);
  1227.  
  1228.     }
  1229.   if (srchPhrase)
  1230.   getString("SEARCH", Opt.Phrase, PHRASE_SIZE, 0);
  1231.   if (Compressed)
  1232.     {
  1233.     if ((Compressed = GetUserCompression()) == NO_COMP)
  1234.     return GOOD_SELECT;
  1235.     doCR();
  1236.  
  1237.     }
  1238.   else Compressed = NO_COMP;
  1239.   download(whichMess, revOrder, protocol, global, Compressed);
  1240.   KillList(&Opt.Users);
  1241.   return GOOD_SELECT;
  1242.  
  1243.   }
  1244. /*
  1245. * UserOptAdd()
  1246. *
  1247. * This adds the given name to a list.
  1248. */
  1249. int UserOptAdd(char *str)
  1250.   {
  1251.   AddData(&Opt.Users, strdup(str), NULL, FALSE);
  1252.   return TRUE;
  1253.  
  1254.   }
  1255. /*
  1256. * FindUser()
  1257. *
  1258. * Is the current user @system _ domain going to match?
  1259. */
  1260. static void *FindUser(char *element, int x)
  1261. /* x is actually not used -- we use global msgBuf */
  1262.   {
  1263.   label User;
  1264.   char System[(2 * NAMESIZE) + 2];
  1265.   System[0] = 0;
  1266.   SepNameSystem(element, User, System, NULL);
  1267.   if (strLen(User) != 0 && matchString(msgBuf.mbauth, User,
  1268.   lbyte(msgBuf.mbauth)) == NULL)
  1269.     {
  1270.     if (strLen(msgBuf.mbto) == 0) return NULL;
  1271.     if (matchString(msgBuf.mbto, User, lbyte(msgBuf.mbto)) == NULL)
  1272.     return NULL;
  1273.  
  1274.     }
  1275.   if (strLen(System) != 0)
  1276.     {
  1277.     if (matchString(msgBuf.mboname, System, lbyte(msgBuf.mboname))
  1278.     == NULL &&
  1279.     matchString(msgBuf.mbdomain, System, lbyte(msgBuf.mbdomain)) == NULL)
  1280.     return NULL;
  1281.  
  1282.     }
  1283.   return element;
  1284.  
  1285.   }
  1286. /*
  1287. * OptionValidate()
  1288. *
  1289. * This is sent to showMessages.
  1290. */
  1291. char OptionValidate(int mode)
  1292.   {
  1293.   if (OptionCheck(mode))
  1294.     {
  1295.     printMessage(0);
  1296.     return Pause_Message_Check();
  1297.  
  1298.     }
  1299.   else mAbort();      /* give a chance to interrupt */
  1300.   return (char)( (mode == 1) ? TRUE : FALSE);
  1301.  
  1302.   }
  1303. /*
  1304. * OptionCheck()
  1305. *
  1306. * This function checks to see if all options fulfilled.
  1307. */
  1308. char OptionCheck(char mode)
  1309.   {
  1310.   long MsgTime;
  1311.   int  rover;
  1312.   if (mode == 1)
  1313.   return (char) (!Opt.LocalOnly && GetFirst(&Opt.Users) == NULL &&
  1314.   strLen(Opt.Phrase) == 0 && Opt.Date == -1l);
  1315.   /* else */
  1316.   /*
  1317.   * If any match failures, don't print.  printMessage(0) indicates a
  1318.   * a print with msg still on disk, while a (1) indicates message now in
  1319.   * the message buffer.
  1320.   */
  1321.   if (Opt.LocalOnly && msgBuf.mboname[0] &&
  1322.   strCmpU(msgBuf.mboname, cfg.codeBuf + cfg.nodeName) != SAMESTRING)
  1323.   return (char)FALSE;
  1324.   if (Opt.Date != -1l)
  1325.   if (ReadDate(msgBuf.mbdate, &MsgTime) != ERROR)
  1326.   if ((!revOrder && MsgTime < Opt.Date) ||
  1327.   (revOrder && MsgTime > Opt.Date))  return (char )FALSE;
  1328.   if (GetFirst(&Opt.Users) != NULL)
  1329.   if (SearchList(&Opt.Users, 0) == NULL) return NULL;
  1330.   if (strLen(Opt.Phrase) != 0)
  1331.     {
  1332.     getMsgStr(getMsgChar, msgBuf.mbtext, MAXTEXT);
  1333.     /* Kill extraneous line breaks */
  1334.     for (rover = 0; msgBuf.mbtext[rover]; rover++)
  1335.     if (msgBuf.mbtext[rover] == NEWLINE &&
  1336.     msgBuf.mbtext[rover + 1] != ' ' &&
  1337.     msgBuf.mbtext[rover + 1] != NEWLINE)
  1338.     msgBuf.mbtext[rover] = ' ';
  1339.     if (matchString(msgBuf.mbtext, Opt.Phrase, lbyte(msgBuf.mbtext))
  1340.     != NULL)
  1341.       {
  1342.       findMessage(msgBuf.mbheadSector, atol(msgBuf.mbId), TRUE);
  1343.       return (char)TRUE;
  1344.  
  1345.       }
  1346.     else return (char)FALSE;
  1347.  
  1348.     }
  1349.   return (char)TRUE;
  1350.  
  1351.   }
  1352. /*
  1353. * doDirectory()
  1354. *
  1355. * This function handles the read directory commands.
  1356. */
  1357. void doDirectory(char doDir, char *fileName, char *phrase)
  1358.   {
  1359.   #ifdef OLD_STYLE
  1360.   extern long BDSizeCount;
  1361.   int   FileCount;
  1362.   if (doDir)
  1363.     {
  1364.     FDSectCount     = 0;      /* global fDir() totals sectors in   */
  1365.     FileCount = wildCard(fDir, fileName, TRUE, phrase, TRUE);
  1366.     mPrintf("\n %d files, approximately %s sectors total\n ", FileCount,
  1367.     PrintPretty(FDSectCount, msgBuf.mbtext));
  1368.  
  1369.     }
  1370.   else
  1371.     {
  1372.     BDSizeCount = 0l;
  1373.     FileCount = wildCard(ShowVerbose, fileName, TRUE, phrase, TRUE);
  1374.     mPrintf("\n %d files, %s bytes total.\n ", FileCount,
  1375.     PrintPretty(BDSizeCount, msgBuf.mbtext));
  1376.  
  1377.     }
  1378.   #else
  1379.   int   FileCount;
  1380.   extern long FDSize;
  1381.   FDSize = 0l;
  1382.   FileCount = wildCard((doDir) ? fDir : ShowVerbose, fileName, TRUE, phrase,
  1383.   TRUE);
  1384.   mPrintf("\n %d files, ", FileCount);
  1385.   mPrintf((doDir) ? "approximately %s sectors total\n " :
  1386.   "%s bytes total.\n ",
  1387.   PrintPretty(FDSize, msgBuf.mbtext));
  1388.   #endif
  1389.   giveSpaceLeft(&roomBuf);
  1390.  
  1391.   }
  1392. #define MAX_USER_ERRORS 25
  1393. /*
  1394. * doRegular()
  1395. *
  1396. * The big fanout.
  1397. */
  1398. char doRegular(char x, char c)
  1399.   {
  1400.   static int errorCount = 0;
  1401.   char       toReturn, cc[2];
  1402.   SListBase  RegSelects =
  1403.     {
  1404.     NULL, FindSelect, NULL, NoFree, NULL
  1405.  
  1406.     };
  1407.   char *RegOpts[] =
  1408.     {
  1409.     TERM "Chat",    TERM "Door",       TERM "!", TERM "Enter",
  1410.     TERM "F\bRead", TERM "Goto",       TERM "+\bGoto",
  1411.     TERM "Read",    TERM "O\bRead",    TERM "N\bRead",
  1412.     TERM "Help",    TERM "Information",TERM "Known rooms",
  1413.     TERM "Login",   TERM "Skip",       TERM "Terminate",
  1414.     TERM "Backup",  TERM "Ungoto",     TERM "-\bBackup",
  1415.     TERM "QWK Mail",TERM "\\",         TERM ";",
  1416.     TERM "Z\bForget", TERM "?",
  1417.      " ",               " ",                ""
  1418.  
  1419.     };
  1420.   char       *legal = "CD!EFG+HIKLMNORSTBU-QZ";
  1421.   toReturn = GOOD_SELECT;
  1422.   if (loggedIn)
  1423.     {
  1424.     if (aide ||
  1425.     (strCmpU(logBuf.lbname, AskForNSMap(&Moderators, thisRoom))
  1426.     == SAMESTRING ||
  1427.     strCmpU(logBuf.lbname, FloorTab[thisFloor].FlModerator)
  1428.     == SAMESTRING))
  1429.     ExtraOption(RegOpts, TERM "Aide special fn:");
  1430.     if (!MeetDisabled)
  1431.       {
  1432.       ExtraOption(RegOpts, TERM "Meet User");
  1433.  
  1434.       }
  1435.     else ExtraOption(RegOpts, TERM "Moo!");
  1436.  
  1437.     }
  1438.  
  1439.    SpecialMessage("Status:User Idle");
  1440.  
  1441.   if (strchr(legal, c) != NULL) errorCount = 0;
  1442.   else        errorCount++;
  1443.   PushBack(c);  /* ugly kludge */
  1444.   if ((cc[0] = c) == 0 ||
  1445.   CmdMenuList(RegOpts, &RegSelects, NULL, cc, x, FALSE) == GOOD_SELECT)
  1446.     {
  1447.     switch (cc[0])
  1448.       {
  1449.       case 'C': toReturn = doChat(  x, '\0');     break;
  1450.       case '!':
  1451.       case 'D': toReturn = doDoor(  x);     break;
  1452.       case 'E': toReturn = doEnter( x, 'M' );     break;
  1453.       case 'F': toReturn = doRead(  x, 'F' );     break;
  1454.       case '+':
  1455.       case 'G': toReturn = doGoto(  x);     break;
  1456.       case 'H': toReturn = doHelp(  x);     break;
  1457.       case 'I': toReturn = doInfo();        break;
  1458.       case 'K': toReturn = doKnown( x);     break;
  1459.       case 'L': toReturn = doLogin( x);     break;
  1460.       case 'M': if (!MeetDisabled) toReturn = doMeet( x); break;
  1461.       case 'N': toReturn = doRead(  x, 'N' );     break;
  1462.       case 'O': toReturn = doRead(  x, 'O' );     break;
  1463.       case 'Q': toReturn = QWKmain();             break;
  1464.       case 'R': toReturn = doRead(  x, 'R' );     break;
  1465.       case 'S': toReturn = doSkip(  x);     break;
  1466.       case 'T': toReturn = doLogout(x, 'Q' );     break;
  1467.       case '-':
  1468.       case 'B': /* k2ne ism */
  1469.       case 'U': toReturn = doUngoto(x);     break;
  1470.       case '\'':
  1471.       case ';': toReturn = DoFloors();      break;
  1472.       case 0:
  1473.       pause(1);          /* To clear line noise */
  1474.       while (MIReady())   inp();   /* eat noise */
  1475.       if (newCarrier)
  1476.         {
  1477.         greeting();
  1478.         newCarrier  = FALSE;
  1479.  
  1480.         }
  1481.       if (justLostCarrier)
  1482.         {
  1483.         justLostCarrier = FALSE;
  1484.         terminate(TRUE, TRUE);
  1485.  
  1486.         }
  1487.       break;  /* irrelevant value */
  1488.       case '?':
  1489.       tutorial("mainopt.mnu", TRUE);
  1490.       if (whichIO == CONSOLE)   mPrintf("\n ^l: SysOp privileged fns\n ");
  1491.       break;
  1492.       case 'A': toReturn = doAide(x, 'E');      break;
  1493.       case 'Z': toReturn = doForget(x);     break;
  1494.       default:
  1495.       if (errorCount > MAX_USER_ERRORS)
  1496.         {
  1497.         logMessage(EVIL_SIGNAL, "", 'E');
  1498.         HangUp(TRUE);
  1499.  
  1500.         }
  1501.       toReturn=BAD_SELECT;
  1502.       break;
  1503.  
  1504.       }
  1505.  
  1506.     }
  1507.   if (toReturn == BACKED_OUT)
  1508.     {
  1509.     PushBack('\b');
  1510.     CmdMenuList(RegOpts, &RegSelects, NULL, cc, FALSE, FALSE);   /* does the BS */
  1511.  
  1512.     }
  1513.   KillList(&RegSelects);
  1514.   return  toReturn;
  1515.  
  1516.   }
  1517. /*
  1518. * doSkip()
  1519. *
  1520. * This function handles the <S>kip a room command.
  1521. */
  1522. char doSkip(char expand)
  1523.   {
  1524.   label roomName;     /* In case of ".Skip" */
  1525.   char  dispbuf[2 * NAMESIZE];
  1526.   int   rover;
  1527.   outFlag = IMPERVIOUS;
  1528.   sPrintf(dispbuf, "%s> goto ", roomTab[thisRoom].rtname);
  1529.   mPrintf("%s", dispbuf);
  1530.   if (expand)
  1531.     {
  1532.     if (getNormStr("", roomName, NAMESIZE, BS_VALID) == BACKED_OUT)
  1533.       {
  1534.       for (rover = 0; rover < strLen(dispbuf); rover++)
  1535.         {
  1536.         mPrintf("\b \b");
  1537.  
  1538.         }
  1539.       return BACKED_OUT;
  1540.  
  1541.       }
  1542.  
  1543.     }
  1544.   else
  1545.   roomName[0] = '\0';
  1546.   if (roomName[0] == '?')
  1547.   tutorial("skip.hlp", TRUE);
  1548.   else
  1549.     {
  1550.     roomTab[thisRoom].rtflags.SKIP = 1;     /* Set bit */
  1551.     gotoRoom(roomName, 'S');
  1552.  
  1553.     }
  1554.   return GOOD_SELECT;
  1555.  
  1556.   }
  1557. /*
  1558. * doSysop()
  1559. *
  1560. * This function handles the sysop-only menu.  It returns FALSE to fall
  1561. * invisibly into default error msg.
  1562. */
  1563. char doSysop()
  1564.   {
  1565.   extern unsigned long S_min, S_max;  /* stack tracking variables */
  1566.   extern char *NoFileStr;
  1567.   MSG_NUMBER  temp;
  1568.   int i;
  1569.   char  systemPW[200];
  1570.  
  1571.  
  1572.   extern char *VERSION, *LCHeld, *netVersion, *SysVers;
  1573.   extern int  fixVers, majorVers;
  1574.   logBuffer   lBuf;   /* This has to be local!  Don't sub logTmp */
  1575.   MenuId  id;
  1576.   char Priv[] = "\n Privileged Functions\n ";
  1577.   char  *CtdlOpts[] =
  1578.     {
  1579.     "A(bort)          ", "B(aud rate)           ", "C(hat mode)\n",
  1580.     "D(ebug mode)     ", "E(cho)                ", "F(ile grab)\n",
  1581.     "I(nformation)    ", "M(ODEM mode)          ", "N(et Menu)\n" ,
  1582.     "O(ther Commands) ", "R(einitialize Modem)  ", "Q(debug)\n",
  1583.     "U(ser Admin)     ", "X(exit from Citadel)\n",
  1584.     #ifdef NEED_MSG_PEEKING
  1585.     "Z ",
  1586.     #endif
  1587.     #ifdef NEED_MSG_LIST
  1588.     "Y ",
  1589.     #endif
  1590.     "1 ",    " W ",    "Z\n",   ""
  1591.  
  1592.     };
  1593.   if ((!onConsole || ConsolePassword) && !remoteSysop)
  1594.     {
  1595.     if (!(onConsole && ConsolePassword && strLen(cfg.sysPassword) == 0))
  1596.       {
  1597.       if ((!aide && !onConsole) || strLen(cfg.sysPassword) == 0)
  1598.         {
  1599.         return BAD_SELECT;
  1600.  
  1601.         }
  1602.       echo  = CALLER;
  1603.       getNormStr("SYSPWD", systemPW, sizeof systemPW, NO_ECHO);
  1604.       echo  = BOTH;
  1605.       if (strCmp(systemPW, cfg.sysPassword) != 0)
  1606.       return BAD_SELECT;
  1607.       remoteSysop = TRUE;
  1608.  
  1609.       }
  1610.  
  1611.     }
  1612.   initLogBuf(&lBuf);
  1613.  
  1614.    SpecialMessage("Status:***Sysop***");
  1615.  
  1616.   if (whichIO == CONSOLE && gotCarrier())
  1617.     Output_Citadel_Message("ONEMOM", NULL, NULL, NULL);
  1618.   id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts, Priv);
  1619.   while (onLine())
  1620.     {
  1621.     outFlag = OUTOK;
  1622.     SysopMenuPrompt(id, "\n privileged fn: ");
  1623.     switch (GetSysopMenuChar(id))
  1624.       {
  1625.       case 'W':
  1626.       EventShow();  /* Debug stuff */
  1627.       break;
  1628.       case '1':
  1629.       for (i = 0; i < MSGSPERRM; i++)
  1630.         {
  1631.         if (findMessage(roomBuf.msg[i].rbmsgLoc, roomBuf.msg[i].rbmsgNo,
  1632.         TRUE))
  1633.           {
  1634.           mPrintf("(%s : %s) ", msgBuf.mbsrcId, msgBuf.mboname);
  1635.  
  1636.           }
  1637.         mPrintf("%ld: %d\n ", roomBuf.msg[i].rbmsgNo,
  1638.         roomBuf.msg[i].rbmsgLoc);
  1639.  
  1640.         }
  1641.       break;
  1642.       #ifdef NEED_MSG_LIST
  1643.       case 'Y':
  1644.       CloseSysopMenu(id);
  1645.       for (i = 0; i < MSGSPERRM; i++)
  1646.         {
  1647.         mPrintf(" Room:%-20s:%ld: %d\n ",
  1648.         roomBuf.msg[i].rbname,
  1649.         roomBuf.msg[i].rbmsgNo,
  1650.         roomBuf.msg[i].rbmsgLoc);
  1651.         if( (i%20) == 19)iChar();
  1652.  
  1653.         };
  1654.       iChar();
  1655.       id = RegisterSysopMenu("ctdlopt.mnu",CtdlOpts,Priv);
  1656.       break;
  1657.       #endif
  1658.       #ifdef NEED_MSG_PEEKING
  1659.       case 'Z':
  1660.       CloseSysopMenu(id);
  1661.       mPeek();
  1662.       iChar();
  1663.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1664.       break;
  1665.       #endif
  1666.       case 'B':
  1667.       changeBauds(id);
  1668.       break;
  1669.       case 'E':
  1670.       sPrintf(systemPW, "%sabled\n ",
  1671.       (anyEcho = !anyEcho) ? "en" : "dis");
  1672.       ScrNewUser();
  1673.       SysopInfoReport(id, systemPW);
  1674.       break;
  1675.       case 'F':
  1676.       SysopRequestString(id, "EFILEN", systemPW, 50, 0);
  1677.       if (!ingestFile(systemPW, &tempMess))
  1678.         {
  1679.         char *fn;
  1680.         fn = strdup(systemPW);
  1681.         sPrintf(systemPW, NoFileStr, fn);
  1682.         SysopError(id, systemPW);
  1683.         free(fn);
  1684.  
  1685.         }
  1686.       break;
  1687.       case 'A':
  1688.       killLogBuf(&lBuf);
  1689.       CloseSysopMenu(id);
  1690.       return GOOD_SELECT;
  1691.       case 'C':
  1692.       cfg.BoolFlags.noChat =  (cfg.BoolFlags.noChat== 1) ? 0 : 1;
  1693.       sPrintf(systemPW, "%sabled\n ",cfg.BoolFlags.noChat ? "dis" : "en" );
  1694.       ScrNewUser();
  1695.       SysopInfoReport(id, systemPW);
  1696.       break;
  1697.       case 'D':
  1698.       cfg.BoolFlags.debug =  (cfg.BoolFlags.debug == 1) ? 0 : 1;
  1699.       sPrintf(systemPW, "%sabled\n ", cfg.BoolFlags.debug ? "en" : "dis");
  1700.       SysopInfoReport(id, systemPW);
  1701.       break;
  1702.       case 'I':
  1703.       sPrintf(msgBuf.mbtext, "\n %s V%s%s\n Net version %s",
  1704.       VARIANT_NAME, VERSION, SysVers, netVersion);
  1705.       sPrintf(lbyte(msgBuf.mbtext), "\n Commands version %d.%d    ", majorVers,
  1706.       fixVers);
  1707.       sPrintf(lbyte(msgBuf.mbtext), "ctdlcnfg.sys version %d\n ",
  1708.       cfg.paramVers);
  1709.       /* sPrintf(lbyte(msgBuf.mbtext), "coreleft is %ld\n ", coreleft()); */
  1710.       sPrintf(lbyte(msgBuf.mbtext), "Stack Usage: Min:%lx Max:%lx Size:%lx\n ",S_min,S_max,(S_max - S_min + 1));
  1711.       if( cfg.Audit != 0)sPrintf(lbyte(msgBuf.mbtext), "You are caller number %ld\n ",Get_Call_Count());
  1712.       sPrintf(lbyte(msgBuf.mbtext), "You have %s privledges\n ",Display_Privledges());
  1713.       ActiveEvents(msgBuf.mbtext);
  1714.       SysopDisplayInfo(id, msgBuf.mbtext, " Info ");
  1715.       break;
  1716.       case 'M':
  1717.       CloseSysopMenu(id);
  1718.       if (whichIO != MODEM)
  1719.         {
  1720.         whichIO = MODEM;
  1721.         setUp(FALSE);
  1722.  
  1723.         }
  1724.       printf("Chat mode %sabled\n ",
  1725.       cfg.BoolFlags.noChat  ?  "dis"  :  "en");
  1726.       if (!gotCarrier())
  1727.         {
  1728.         EnableModem(FALSE);
  1729.         ReInitModem();
  1730.  
  1731.         }
  1732.       #ifdef NEED_VISIBLE
  1733.       if (visibleMode) mPrintf("Visible mode on\n ");
  1734.       #endif
  1735.       killLogBuf(&lBuf);
  1736.       ScrNewUser();
  1737.       startTimer(NEXT_ANYNET);      /* start up anytime net timer */
  1738.       if (gotCarrier()) mPrintf("System on-line\n ");
  1739.       return GOOD_SELECT;
  1740.       case 'O':
  1741.       CloseSysopMenu(id);
  1742.       systemCommands();
  1743.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1744.       break;
  1745.       #ifdef MAKE_AVAILABLE
  1746.       case 'S':
  1747.       changeDate();
  1748.       break;
  1749.       #endif
  1750.       #ifdef NEED_VISIBLE
  1751.       case 'V':
  1752.       mPrintf(" VisibleMode==%d\n ",  visibleMode = !visibleMode);
  1753.       break;
  1754.       #endif
  1755.       case ERROR:
  1756.       case 'X':
  1757.       if (!SysopGetYesNo(id, NULL, "CONFRM")) break;
  1758.       ExitToMsdos = TRUE;
  1759.       exitValue   = (remoteSysop && !onConsole) ? REMOTE_SYSOP_EXIT : SYSOP_EXIT;
  1760.       CloseSysopMenu(id);
  1761.       return GOOD_SELECT;
  1762.       case 'N':
  1763.       CloseSysopMenu(id);
  1764.       netStuff();
  1765.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts, Priv);
  1766.       break;
  1767.       case 'R':
  1768.       if (gotCarrier()) HangUp(TRUE);
  1769.       Reinitialize();
  1770.       break;
  1771.       case 'Q':
  1772.       temp = SysopGetNumber(id, "SETOLD", 0l, 200000l);
  1773.       if (temp != 0l) cfg.oldest = temp;
  1774.       break;
  1775.       case 'U':
  1776.       CloseSysopMenu(id);
  1777.       UserAdmin(&lBuf);
  1778.       id = RegisterSysopMenu("ctdlopt.mnu", CtdlOpts,Priv);
  1779.       break;
  1780.  
  1781.       }
  1782.  
  1783.     }
  1784.   killLogBuf(&lBuf);
  1785.   CloseSysopMenu(id);
  1786.   return GOOD_SELECT;
  1787.  
  1788.   }
  1789. /*
  1790. * doUngoto()
  1791. *
  1792. * This function handles the Ungoto command.
  1793. */
  1794. char doUngoto(char moreYet)
  1795.   {
  1796.   label target;
  1797.   if (!moreYet)
  1798.     {
  1799.     strCpy(target, "");
  1800.  
  1801.     }
  1802.   else
  1803.     {
  1804.     if (getNormStr("", target, NAMESIZE, BS_VALID) == BACKED_OUT)
  1805.     return BACKED_OUT;
  1806.  
  1807.     }
  1808.   retRoom(target);
  1809.   return GOOD_SELECT;
  1810.  
  1811.   }
  1812. /*
  1813. * getCommand()
  1814. *
  1815. * This function prints the menu prompt and gets command char and returns a
  1816. * char via parameter and expand flag as value -- i.e., TRUE if parameters
  1817. * follow else FALSE.
  1818. */
  1819. char getCommand(char *c, char bs)
  1820.   {
  1821.   char expand, again;
  1822.   outFlag = OUTOK;
  1823.   if (!bs)
  1824.   givePrompt();
  1825.   do
  1826.     {
  1827.     again = FALSE;
  1828.     /* bizarre cheat */
  1829.     if (!bs)
  1830.       {
  1831.       if( justLostCarrier )
  1832.         {
  1833.         *c = 0;
  1834.  
  1835.         }
  1836.       else
  1837.         {
  1838.         *c = modIn();
  1839.         *c = toUpper(*c);
  1840.  
  1841.         };
  1842.  
  1843.       }
  1844.     else *c = '.';
  1845.     expand  = ( *c == ' ' || *c == '.' || *c == ',' || *c == '/' );
  1846.     if (expand)
  1847.       {
  1848.       if (!bs) oChar(*c);
  1849.       *c = modIn();
  1850.       if ((*c = toUpper(*c)) == '\b')
  1851.         {
  1852.         mPrintf("\b \b");
  1853.         again = TRUE;
  1854.  
  1855.         }
  1856.  
  1857.       }
  1858.     /* catch a late Pause, et al, command */
  1859.     else if (*c == 'P' || *c == '\b') again = TRUE;
  1860.     else if (*c == 7)
  1861.       {
  1862.       if( CheckForSpecial(13,69))netController(0,0,NO_NETS, ANY_CALL,0);
  1863.       }
  1864.     /* else oChar(*c); -- actually, handled somewhere else! */
  1865.     bs = FALSE;
  1866.  
  1867.     }
  1868.   while (again && onLine());
  1869.   if (justLostCarrier)
  1870.     {
  1871.     justLostCarrier = FALSE;
  1872.     terminate(TRUE, TRUE);
  1873.     expand = 0;
  1874.  
  1875.     }
  1876.   return expand;
  1877.  
  1878.   }
  1879. /*
  1880. * greeting()
  1881. *
  1882. * This gives system-entry blurb etc.
  1883. */
  1884. void greeting()
  1885.   {
  1886.   extern char *VERSION, *SysVers;
  1887.   extern int logTries;
  1888.   if (loggedIn) terminate(FALSE, TRUE);
  1889.   setUp(TRUE);     pause(10);
  1890.   logTries = 1; /* put this here instead of setUp() */
  1891.   PrintBanner = TRUE; /* signal for anytime net */
  1892.   doCR();
  1893.   expert = TRUE;
  1894.   HelpIfPresent("banner.pre");
  1895.   if (!MultiBanner("banner"))
  1896.   if (!HelpIfPresent("banner.blb"))
  1897.     Output_Citadel_Message("NODETL",NULL,NULL,NULL);
  1898.   HelpIfPresent("banner.sfx");
  1899.   expert = FALSE;
  1900.   Output_Citadel_Message("VERSIN",NULL,NULL,NULL);
  1901.   Output_Citadel_Message("HELPOP",NULL,NULL,NULL);
  1902.   printf("Chat mode %sabled\n", cfg.BoolFlags.noChat ? "dis" : "en");
  1903.   printf("\n 'MODEM' mode.\n "      );
  1904.   printf("(<ESC> for CONSOLE mode.)\n "   );
  1905.   while (MIReady())
  1906.   inp();
  1907.   gotoRoom(baseRoom, 'R');
  1908.   setUp(TRUE);
  1909.   PrintBanner = FALSE;
  1910.   if (outFlag == NET_CALL)
  1911.     {
  1912.     netController(0, 0, NO_NETS, ANY_CALL, 0);   /* so we don't call out */
  1913.  
  1914.     }
  1915.   else if (outFlag == STROLL_DETECTED)
  1916.     {
  1917.     StrollIt();
  1918.  
  1919.     }
  1920.   outFlag = OUTOK;
  1921.  
  1922.   }
  1923. /*
  1924. * main()
  1925. *
  1926. * This is the main manager.
  1927. */
  1928. void main(int argc, char **argv)
  1929.   {
  1930.   extern char results_debug;  /* turn on to debug modem results codes */
  1931.   extern char results_cid;    /* turn on to collect caller ID info if present */
  1932.   extern char logNetResults, netDebug, DisVandals,
  1933.   VortexHandle, BpsSet, *kip, ItlWxmodem, Zmodem, NoConsoleBanner;
  1934.   extern int  ParanoiaLimit, LD_Delay;
  1935.   extern long LowFree;
  1936.   char c, x, errMsg;
  1937.   int  CmdResult = GOOD_SELECT;
  1938.   cfg.weAre   = CITADEL;
  1939.   errMsg = FALSE;
  1940.   while (argc >= 2)
  1941.     {
  1942.     argc--;
  1943.     if (strCmpU(argv[argc], "+netlog") == SAMESTRING)
  1944.       {
  1945.       logNetResults = TRUE;
  1946.       }
  1947.     else if (strncmp(argv[argc], "+results", 4) == SAMESTRING)
  1948.       {
  1949.       results_debug = TRUE;
  1950.       }
  1951.     else if (strncmp(argv[argc], "+cid", 4) == SAMESTRING)
  1952.       {
  1953.       results_cid   = TRUE;
  1954.       }
  1955.     else if (strncmp(argv[argc], "kip=", 4) == SAMESTRING)
  1956.       {
  1957.       kip = argv[argc] + 4;
  1958.  
  1959.       }
  1960.     else if (strncmp(argv[argc], "lowfree=", 8) == SAMESTRING)
  1961.       {
  1962.       LowFree = atoi(argv[argc] + 8);
  1963.  
  1964.       }
  1965.     else if (strncmp(argv[argc], "lddelay=", 8) == SAMESTRING)
  1966.       {
  1967.       LD_Delay = atoi(argv[argc] + 8);
  1968.  
  1969.       }
  1970.     else if (strncmp(argv[argc], "paranoia=", 9) == SAMESTRING)
  1971.       {
  1972.       if ((ParanoiaLimit = atoi(argv[argc] + 9)) < 1)
  1973.       ParanoiaLimit = 10000;
  1974.  
  1975.       }
  1976.     else if (strncmp(argv[argc], "bps=", 4) == SAMESTRING)
  1977.       {
  1978.       BpsSet = TRUE;
  1979.       ReadBps(argv[argc]);
  1980.  
  1981.       }
  1982.     else if (strCmpU(argv[argc], "+netdebug") == SAMESTRING)
  1983.       {
  1984.       netDebug = TRUE;
  1985.  
  1986.       }
  1987.     else if (strCmpU(argv[argc], "+nochat") == SAMESTRING)
  1988.       {
  1989.       NoChatAtAll = TRUE;
  1990.  
  1991.       }
  1992.     else if (strCmpU(argv[argc], "+nomeet") == SAMESTRING)
  1993.       {
  1994.       MeetDisabled = TRUE;
  1995.  
  1996.       }
  1997.     else if (strCmpU(argv[argc], "+noecho") == SAMESTRING)
  1998.       {
  1999.       anyEcho = FALSE;
  2000.  
  2001.       }
  2002.     else if (strCmpU(argv[argc], "+wx") == SAMESTRING)
  2003.       {
  2004.       #ifdef WXMODEM_AVAILABLE
  2005.       ItlWxmodem = TRUE;
  2006.       #endif
  2007.  
  2008.       }
  2009.     else if (strCmpU(argv[argc], "+vortex") == SAMESTRING)
  2010.       {
  2011.       VortexHandle = TRUE;
  2012.  
  2013.       }
  2014.     else if (strCmpU(argv[argc], "-vortex") == SAMESTRING)
  2015.       {
  2016.       VortexHandle = FALSE;
  2017.  
  2018.       }
  2019.     else if (strCmpU(argv[argc], "+vandaloff") == SAMESTRING)
  2020.       {
  2021.       DisVandals = TRUE;
  2022.  
  2023.       }
  2024.     else if (strCmpU(argv[argc], "+conpwd") == SAMESTRING)
  2025.       {
  2026.       ConsolePassword = TRUE;
  2027.  
  2028.       }
  2029.     else if (strCmpU(argv[argc], "+noconban") == SAMESTRING)
  2030.       {
  2031.       NoConsoleBanner = TRUE;
  2032.  
  2033.       }
  2034.     else if (strncmp(argv[argc], "zmodem=", 7) == SAMESTRING)
  2035.       {
  2036.       Zmodem = argv[argc][7];
  2037.  
  2038.       }
  2039.     else
  2040.       {
  2041.       printf("Invalid  argument: %s\n", argv[argc]);
  2042.       errMsg = TRUE;
  2043.  
  2044.       }
  2045.  
  2046.     }
  2047.   if (initCitadel())
  2048.     {
  2049.     greeting();
  2050.     logMessage(FIRST_IN, "", FALSE);
  2051.  
  2052.     }
  2053.   startTimer(NEXT_ANYNET);      /* start anytime net timer */
  2054.   if (errMsg)
  2055.     {
  2056.     sPrintf(msgBuf.mbtext, "System brought up from apparent crash.");
  2057.     aideMessage(NULL,FALSE);
  2058.  
  2059.     }
  2060.   while (!ExitToMsdos)
  2061.     {
  2062.     x       = getCommand(&c, (CmdResult == BACKED_OUT));
  2063.     outFlag = OUTOK;
  2064.     CmdResult = (c==CNTRLl)  ?  doSysop() : doRegular(x, c);
  2065.     if (CmdResult == BAD_SELECT)
  2066.       {
  2067.       Output_Citadel_Message("HLPMNU",NULL,NULL,NULL);
  2068.       }
  2069.  
  2070.     }
  2071.   if (loggedIn)
  2072.   terminate( /* hangUp == */ exitValue == DOOR_EXIT ? FALSE : TRUE, TRUE);
  2073.   logMessage(exitValue != DOOR_EXIT ? LAST_OUT : DOOR_OUT , "", FALSE);
  2074.   writeSysTab();
  2075.   if (onConsole) EnableModem(FALSE);  /* just in case... */
  2076.   if (exitValue != DOOR_EXIT && !cfg.BoolFlags.IsDoor) DisableModem(TRUE);
  2077.   ModemShutdown(((exitValue == DOOR_EXIT || cfg.BoolFlags.IsDoor) && !onConsole) ? FALSE : TRUE);
  2078.   systemShutdown(0);
  2079.   exit(exitValue);
  2080.  
  2081.   }
  2082. /*
  2083. * UserAdmin()
  2084. *
  2085. * This function handles the user administration menu.
  2086. */
  2087. void UserAdmin(logBuffer *lBuf)
  2088.   {
  2089.   extern SListBase MailForward;
  2090.   int      logNo, ltabSlot, result;
  2091.   SYS_FILE killHeld;
  2092.   label    who;
  2093.   MenuId   id;
  2094.   char User_Prompt[] = "\nUser Administration\n ";
  2095.   char     *UserOpts[] =
  2096.     {
  2097.     "A(dd new user)     ", "D(oor privs)  ", "E(ndless User)\n",
  2098.     "F(ile privs)       ", "K(ill user)   ", "N(et privs)\n",
  2099.     "P(rivileges-aide)  ", "T(wit)        ", "X(eXit)\n",
  2100.     ""
  2101.  
  2102.     };
  2103.   id = RegisterSysopMenu("useropt.mnu", UserOpts, User_Prompt);
  2104.   while (onLine())
  2105.     {
  2106.     outFlag = OUTOK;
  2107.     SysopMenuPrompt(id, "\n user admin fn: ");
  2108.     switch (GetSysopMenuChar(id))
  2109.       {
  2110.       case ERROR:
  2111.       case 'X': CloseSysopMenu(id); return ;
  2112.       case 'E': /* permanent account administration */
  2113.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2114.       logNo == cfg.MAXLOGTAB) break;
  2115.       Output_Citadel_Message((lBuf->lbflags.PERMANENT ? "NPERMA" : "PERMAC")
  2116.                             ,(long)lBuf->lbname,NULL,NULL);
  2117.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2118.       lBuf->lbflags.PERMANENT = !lBuf->lbflags.PERMANENT;
  2119.       putLog(lBuf, logNo);
  2120.       /* find position in logTab[] and update that, too */
  2121.       if ((ltabSlot = PWSlot(lBuf->lbpw, /* load == */ FALSE)) != ERROR)
  2122.       logTab[ltabSlot].ltpermanent = lBuf->lbflags.PERMANENT;
  2123.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2124.       logBuf.lbflags.PERMANENT = lBuf->lbflags.PERMANENT;
  2125.       break;
  2126.       case 'T':
  2127.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2128.       logNo == cfg.MAXLOGTAB) break;
  2129.  
  2130.       Output_Citadel_Message((lBuf->lbflags.TWIT ? "TWITST" : "TWITNT")
  2131.                             ,(long)lBuf->lbname,NULL,NULL);
  2132.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2133.  
  2134.       lBuf->lbflags.TWIT = !lBuf->lbflags.TWIT;
  2135.  
  2136.       putLog(lBuf, logNo);
  2137.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2138.       logBuf.lbflags.TWIT = lBuf->lbflags.TWIT;
  2139.       break;
  2140.       case 'F':
  2141.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR) break;
  2142.       if (logNo == cfg.MAXLOGTAB)
  2143.         {
  2144.         result = DoAllQuestion("GVFLPR","TAFLPR");
  2145.         if (result == ERROR) break;
  2146.         for (logNo = 0; logNo < cfg.MAXLOGTAB; logNo++)
  2147.           {
  2148.           getLog(lBuf, logNo);
  2149.           if (!onConsole) mPrintf(".");
  2150.           if (lBuf->lbflags.L_INUSE && lBuf->lbflags.DL_PRIVS != result)
  2151.             {
  2152.             lBuf->lbflags.DL_PRIVS = result;
  2153.             putLog(lBuf, logNo);
  2154.  
  2155.             }
  2156.  
  2157.           }
  2158.         break;
  2159.  
  2160.         }
  2161.       Output_Citadel_Message((lBuf->lbflags.DL_PRIVS ? "NFLPRI" : "FILPRI")
  2162.                             ,(long)lBuf->lbname,NULL,NULL);
  2163.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2164.  
  2165.       lBuf->lbflags.DL_PRIVS = !lBuf->lbflags.DL_PRIVS;
  2166.       putLog(lBuf, logNo);
  2167.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2168.       logBuf.lbflags.DL_PRIVS = lBuf->lbflags.DL_PRIVS;
  2169.       break;
  2170.       case 'K':
  2171.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2172.       logNo == cfg.MAXLOGTAB) break;
  2173.       Output_Citadel_Message( "KILLTH",(long)lBuf->lbname,lBuf->credit,NULL);
  2174.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2175.       ltabSlot = PWSlot(lBuf->lbpw, /* load == */ FALSE);
  2176.       lBuf->lbname[0] = '\0';
  2177.       lBuf->lbpw[0  ] = '\0';
  2178.       lBuf->lbflags.L_INUSE = FALSE;
  2179.       putLog(lBuf, logNo);
  2180.       logTab[ltabSlot].ltpwhash       = 0;
  2181.       logTab[ltabSlot].ltnmhash       = 0;
  2182.       if (cfg.BoolFlags.HoldOnLost)
  2183.         {
  2184.         sPrintf(msgBuf.mbtext, LCHeld, logNo);
  2185.         makeSysName(killHeld, msgBuf.mbtext, &cfg.holdArea);
  2186.         unlink(killHeld);
  2187.  
  2188.         }
  2189.       KillData(&MailForward, who);
  2190.       UpdateForwarding();
  2191.       break;
  2192.       case 'P':
  2193.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR ||
  2194.       logNo == cfg.MAXLOGTAB) break;
  2195.       if (lBuf->lbflags.AIDE == 1)
  2196.         {
  2197.         lBuf->lbflags.AIDE = 0;
  2198.         lBuf->lbgen[AIDEROOM] = ((roomTab[AIDEROOM].rtgen-1) % MAXGEN)
  2199.         << GENSHIFT;
  2200.  
  2201.         }
  2202.       else
  2203.         {
  2204.         lBuf->lbflags.AIDE = 1;
  2205.         lBuf->lbgen[AIDEROOM] = roomTab[AIDEROOM].rtgen << GENSHIFT;
  2206.         lBuf->lbgen[AIDEROOM] += MAXVISIT-1;
  2207.  
  2208.         }
  2209.       Output_Citadel_Message((lBuf->lbflags.AIDE ? "AIDPRI" : "NADPRI" )
  2210.                             ,(long)lBuf->lbname,NULL,NULL);
  2211.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2212.       putLog(lBuf, logNo);
  2213.       /* see if it is us: */
  2214.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2215.         {
  2216.         aide = (lBuf->lbflags.AIDE == 1) ? TRUE : FALSE;
  2217.         logBuf.lbgen[AIDEROOM] = lBuf->lbgen[AIDEROOM];
  2218.  
  2219.         }
  2220.       break;
  2221.       case 'D':
  2222.       if ((logNo = GetUser(who, lBuf, TRUE)) == ERROR) break;
  2223.       if (logNo == cfg.MAXLOGTAB)
  2224.         {
  2225.         result = DoAllQuestion("GVDRPR","TADRPR");
  2226.         if (result == ERROR) break;
  2227.         for (logNo = 0; logNo < cfg.MAXLOGTAB; logNo++)
  2228.           {
  2229.           getLog(lBuf, logNo);
  2230.           if (!onConsole) mPrintf(".");
  2231.           if (lBuf->lbflags.L_INUSE && lBuf->lbflags.DOOR_PRIVS != result)
  2232.             {
  2233.             lBuf->lbflags.DOOR_PRIVS = result;
  2234.             putLog(lBuf, logNo);
  2235.  
  2236.             }
  2237.  
  2238.           }
  2239.         break;
  2240.  
  2241.         }
  2242.       lBuf->lbflags.DOOR_PRIVS  = (lBuf->lbflags.DOOR_PRIVS == 1) ? 0 : 1;
  2243.       Output_Citadel_Message((lBuf->lbflags.DOOR_PRIVS ? "DORPRI" : "NDRPRI")
  2244.                             ,(long)lBuf->lbname,NULL,NULL);
  2245.       if (!SysopGetYesNo(id, NULL, "CONFRM"))   break;
  2246.  
  2247.       putLog(lBuf, logNo);
  2248.       /* see if it is us: */
  2249.       if (loggedIn  &&  strCmpU(logBuf.lbname, who)==SAMESTRING)
  2250.         {
  2251.         DoorPriv = lBuf->lbflags.DOOR_PRIVS;
  2252.  
  2253.         }
  2254.       break;
  2255.       case 'N':
  2256.       NetPrivs(who);
  2257.       break;
  2258.       case 'A':
  2259.       CloseSysopMenu(id);
  2260.       newUser(&logTmp);
  2261.       id = RegisterSysopMenu("useropt.mnu", UserOpts, User_Prompt);
  2262.       break;
  2263.  
  2264.       }
  2265.  
  2266.     }
  2267.  
  2268.   }
  2269.